package com.nanyang.tms.common.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;
import com.nanyang.common.core.dict.CommonEnum;
import com.nanyang.common.tool.utils.uuid.UUIDUtil;
import com.nanyang.tms.common.exception.TmsManagerException;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

@Slf4j
public class PdfUtils {


    /**
     * 打印面单
     * @param templatePath PDF模板文件的路径
     * @param outputPath   生成的PDF文件的路径
     * @param map          往PDF模板文件中填充的数据
     */
    public static String tagPrint(String templatePath, String outputPath, Map<String, Object> map) throws TmsManagerException {
       /******根据模版pdf 和数据生成新的字节输出流********/
        PdfStamper stamper= null;
        PdfReader reader= null;
        ByteArrayOutputStream bos=null;
        try {
            reader = new PdfReader(templatePath);// 读取pdf模板
            FileUtil.mkdir(outputPath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            form.addSubstitutionFont(bf);
            Map<String, AcroFields.Item> fieldMap = form.getFields();
            //遍历表单域，给表单域赋值
            for (Map.Entry<String, AcroFields.Item> entry : fieldMap.entrySet()) {
                String name = entry.getKey();
//                if (name.contains("image")){//forecastVO.supplierNo_image
//                    String key=name.split("_")[0];
//                    String path = outputPath+ UUIDUtil.uuid()+".png";
//                    Object fieldValueByName = getFieldValueByName(key.split("\\.")[1], map.get(key.split("\\.")[0]));
//                    //条形码存放地址
//                    form.setField(name, BarcodeUtils.generateFile(String.valueOf(fieldValueByName), path));
//                }else if(name.contains(".")){//forecastVO.supplierNo
//                        String key=name.split("\\.")[0];
//                        String valueKey=name.split("\\.")[1];
//                        Object fieldValueByName = getFieldValueByName(valueKey, map.get(key));
//                        if(fieldValueByName instanceof Date){
//                            String s = DateUtil.formatDateTime((Date)fieldValueByName);
//                            form.setField(name, s);
//                        }else{
//                            form.setField(name, String.valueOf(fieldValueByName) );
//                        }
//                }else{
//                       form.setField(name, String.valueOf( map.get(name)));
//                }
                form.setField(name, String.valueOf( map.get(name)));

            }
            //如果为false那么生成的PDF文件还能编辑，一定要设为true
            stamper.setFormFlattening(true);

        } catch (Exception e) {
            log.error("异常发生错误码：{} ，错误信息：{}", CommonEnum.SYSTEM_EXCEPTION.getCode(), CommonEnum.SYSTEM_EXCEPTION.getMessage(), e);
            throw  new TmsManagerException(CommonEnum.SYSTEM_EXCEPTION.getCode(),CommonEnum.SYSTEM_EXCEPTION.getMessage(),e.getMessage());
        }finally {
            StreamRegistry.close(stamper,reader);
        }
        /******新画一个pdf，将字节流输出了到新的pdf上，注意一定要关闭之前的流，否则会抛异常****/
        return flushDocument(outputPath,bos);
    }


    /**
     * 打印交货清单
     * @param templatePath PDF模板文件的路径
     * @param outputPath   生成的PDF文件的路径
     * @param map          往PDF模板文件中填充的数据
     */
    public static String printList(String templatePath, String outputPath, Map<String, Object> map) {
        /******根据模版pdf 和数据生成新的字节输出流********/
        PdfStamper stamper= null;
        PdfReader reader= null;
        ByteArrayOutputStream bos=null;
        try {
            reader = new PdfReader(templatePath);// 读取pdf模板
            FileUtil.mkdir(outputPath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);

            AcroFields form = stamper.getAcroFields();
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            form.addSubstitutionFont(bf);
            Map<String, AcroFields.Item> fieldMap = form.getFields();
            //遍历表单域，给表单域赋值
            for (Map.Entry<String, AcroFields.Item> entry : fieldMap.entrySet()) {
                String name = entry.getKey();
                if (name.contains("image")){//forecastVO.supplierNo_image
                    String key=name.split("_")[0];
                    String path = outputPath+ UUIDUtil.uuid()+".png";

                    //条形码存放地址
                    form.setField(name,BarcodeUtils.generateFile(String.valueOf(map.get(key)), path));
                }else{
                    Object fieldValue= map.get(name);
                    if(fieldValue instanceof Date){
                        String s = DateUtil.formatDateTime(new DateTime());
                        form.setField(name, s);
                    }else{
                        form.setField(name, String.valueOf(fieldValue) );
                    }
                }

            }
            //如果为false那么生成的PDF文件还能编辑，一定要设为true
            stamper.setFormFlattening(true);
        } catch (Exception e) {
            log.error("异常发生错误码：{} ，错误信息：{}", CommonEnum.SYSTEM_EXCEPTION.getCode(), e);
            throw new TmsManagerException(CommonEnum.SYSTEM_EXCEPTION.getCode(),CommonEnum.SYSTEM_EXCEPTION.getMessage(),e.getMessage());
        }finally {
            StreamRegistry.close(stamper,reader);
        }

        /******新画一个pdf，将字节流输出了到新的pdf上，注意一定要关闭之前的流，否则会抛异常****/
        return flushDocument(outputPath,bos);
    }

    private static String flushDocument(String outputPath,ByteArrayOutputStream bos){
        Document doc =null;
        PdfCopy copy = null;
        PdfReader pdfReader=null;
        String pathFile= "";
        try {
            pathFile = outputPath+ UUIDUtil.uuid()+ ".pdf";
            FileOutputStream out = new FileOutputStream(pathFile);
            doc = new Document();
            copy = new PdfCopy(doc, out);
            doc.open();
            pdfReader = new PdfReader(bos.toByteArray());
            PdfImportedPage importPage = copy.getImportedPage(pdfReader, 1);
            copy.addPage(importPage);
        } catch (Exception e) {
            log.error("异常发生错误码：{} ，错误信息：{}", CommonEnum.SYSTEM_EXCEPTION.getCode(), CommonEnum.SYSTEM_EXCEPTION.getMessage(), e);
            throw  new TmsManagerException(CommonEnum.SYSTEM_EXCEPTION.getCode(),CommonEnum.SYSTEM_EXCEPTION.getMessage(),e.getMessage());
        } finally {
            StreamRegistry.closePdf(doc,copy,pdfReader,bos);
        }
        return pathFile;
    }
    private static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[] {});
            return value;
        } catch (Exception e) {
            log.error("获取属性值失败！" + e, e);
            throw new TmsManagerException(CommonEnum.SYSTEM_EXCEPTION.getCode(),CommonEnum.SYSTEM_EXCEPTION.getMessage(),e.getMessage());
        }
    }


    public static void mergePdf(List<String> files, String newfile) throws TmsManagerException{
        Document document =null;
        PdfCopy copy = null;
        try {
            document = new Document(new PdfReader(files.get(0)).getPageSize(1));
            copy = new PdfCopy(document, new FileOutputStream(newfile));
            document.open();
            for (int i = 0; i < files.size(); i++) {
                PdfReader reader = new PdfReader(files.get(i));
                int n = reader.getNumberOfPages();
                for (int j = 1; j <= n; j++) {
                    document.newPage();
                    PdfImportedPage page = copy.getImportedPage(reader, j);
                    copy.addPage(page);
                }
                reader.close();
            }
        }  catch (Exception e) {
            log.error("mergePdf！" + e, e);
            throw new TmsManagerException(CommonEnum.SYSTEM_EXCEPTION.getCode(),CommonEnum.SYSTEM_EXCEPTION.getMessage(),e.getMessage());
        } finally {
            StreamRegistry.closeDocument(document,copy);
        }

    }
    public static  void TestStreams(String filepath) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(filepath);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PdfReader.unethicalreading = true;
        PdfStamper stamper = new PdfStamper(reader, bos);
        stamper.close();
        byte[] result = bos.toByteArray();
        //The error is in the following line
        PdfReader reader2 = new PdfReader(result);
    }
    public static void main(String[] args) throws IOException, DocumentException {
         /* String[] files = {"/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/FC23021616401931760.pdf", "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/FC23022115444429415.pdf"};
        String savepath = "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/44.pdf";
        mergePdf(Arrays.asList(files), savepath);*/

        String templ = "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/69fce00b786d4cf58fb0d63613e68885.pdf";

        TestStreams(templ);


//        String[] files = {"/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/FC23021616401931760.pdf", "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/FC23022115444429415.pdf"};
//
//        String savepath = "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/44.pdf";
//        PdfReader pdfReader = new PdfReader(savepath);
//        PdfReader pdfReader1 = new PdfReader(savepath);
//        for (int i = 0; i < 2; i++) {
//            TestThread tt1 = new TestThread("A"+i);
//            tt1.start();
//        }
//        TestThread tt1 = new TestThread("A");
//        TestThread tt2 = new TestThread("B");
//        TestThread tt3 = new TestThread("C");
//        TestThread tt4 = new TestThread("D");
//        TestThread tt5 = new TestThread("E");
//        TestThread tt6 = new TestThread("F");
//        TestThread tt7 = new TestThread("G");
//        TestThread tt8 = new TestThread("H");
//
//        tt1.start();
//        tt2.start();
//        tt3.start();
//        tt4.start();
//        tt5.start();
//        tt6.start();
//        tt7.start();
//        tt8.start();
        //mergePdf(Arrays.asList(files), savepath);
    }

    static class TestThread extends Thread{
        String name;
        public TestThread(String name){
            this.name=name;
        }
        @Override
        public void run() {
            for (int i = 0; i < 1; i++) {
                String savepath = "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/44/";
                String templ = "/Users/lv/Documents/workspace/nanyang-cloud/nanyang-cloud/69fce00b786d4cf58fb0d63613e68885.pdf";
                HashMap<String, Object> map = new HashMap<>();
                map.put("forecastVO.saleProductName","111");
                map.put("forecastVO.countyCode","111");
                map.put("forecastVO.countyName","111");
                map.put("forecastReceiverVO.address","111");
                map.put("forecastSenderVO.senderCountyName","111");
                map.put("forecastSenderVO.address","111");
                map.put("forecastVO.num","111");
                map.put("forecastVO.cargoTypeName","111");
                map.put("forecastVO.supplierNo_image","111");
                map.put("forecastVO.customerNo","111");
                long startJobTs = System.currentTimeMillis();
                tagPrint(templ,savepath,map);
                System.out.println("总耗时:" + (System.currentTimeMillis() - startJobTs) + "ms");
                System.out.println(this.name+":"+i);
            }
        }
    }

}
